/*!
 * \file WTSDataFactory.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief 数据工厂类定义
 * 
 * \details 该文件定义了WonderTrader的数据工厂类，负责：
 *          - K线数据的构建和更新
 *          - 不同周期K线数据的提取和转换
 *          - Tick数据到K线数据的转换
 *          - K线数据的合并操作
 *          
 *          支持的K线周期包括：秒线、分钟线、5分钟线、日线等，
 *          可以处理实时数据更新和历史数据提取。
 */
#pragma once
#include "../Includes/IDataFactory.h"

USING_NS_WTP;

/*!
 * \class WTSDataFactory
 * \brief WonderTrader数据工厂实现类
 * 
 * \details 数据工厂类实现了IDataFactory接口，提供以下核心功能：
 *          
 *          **K线数据更新**：
 *          - 基于tick数据实时更新K线
 *          - 基于基础K线数据更新高级K线
 *          - 支持多种时间周期（秒、分钟、5分钟、日线）
 *          
 *          **K线数据提取**：
 *          - 从基础K线提取指定周期的K线数据
 *          - 从tick数据序列构建K线数据
 *          - 支持是否包含未闭合K线的选项
 *          
 *          **数据合并**：
 *          - 合并多个K线数据集
 *          - 保证数据的连续性和完整性
 *          
 *          **时间处理**：
 *          - 交易时段管理
 *          - Unix时间戳转换
 *          - 时间区间计算
 *          
 * \note 该类是线程安全的，可以在多线程环境中使用
 * \see IDataFactory, WTSKlineData, WTSTickData
 */
class WTSDataFactory : public IDataFactory
{
public:
	/*!
	 * \brief 基于tick数据更新K线
	 * 
	 * \param klineData K线数据容器
	 * \param tick 新的tick数据
	 * \param sInfo 交易时段模板
	 * \return 返回更新后的K线结构，如果没有更新则返回NULL
	 * 
	 * \details 根据传入的tick数据实时更新K线数据，包括：
	 *          - 开盘价、最高价、最低价、收盘价的更新
	 *          - 成交量和成交额的累计
	 *          - 时间戳的更新
	 *          - 是否需要生成新K线的判断
	 * 
	 * \note 该方法会自动判断K线周期并调用相应的更新函数
	 * \see updateMin1Data(), updateMin5Data(), updateDayData(), updateSecData()
	 */
	virtual WTSBarStruct*	updateKlineData(WTSKlineData* klineData, WTSTickData* tick, WTSSessionInfo* sInfo);

	/*!
	 * \brief 基于基础K线数据更新高级K线
	 * 
	 * \param klineData 目标K线数据容器
	 * \param newBasicBar 新的基础K线数据
	 * \param sInfo 交易时段模板
	 * \return 返回更新后的K线结构，如果没有更新则返回NULL
	 * 
	 * \details 基于已有的基础K线数据（如1分钟线）来更新高级K线数据（如5分钟线、日线）：
	 *          - 时间对齐和周期判断
	 *          - OHLC数据的合并计算
	 *          - 成交量和持仓量的累计
	 *          - 新K线的生成和旧K线的更新
	 * 
	 * \note 通常用于从低频数据构建高频数据
	 * \see updateMin5Data(), updateDayData()
	 */
	virtual WTSBarStruct*	updateKlineData(WTSKlineData* klineData, WTSBarStruct* newBasicBar, WTSSessionInfo* sInfo);

	/*!
	 * \brief 从基础K线数据中提取指定周期的K线数据
	 * 
	 * \param baseKline 基础K线数据切片
	 * \param period 目标周期类型（m1/m5/day等）
	 * \param times 周期倍数
	 * \param sInfo 交易时段模板
	 * \param bIncludeOpen 是否包含未闭合的K线，默认为true
	 * \return 返回提取的K线数据，调用者负责释放内存
	 * 
	 * \details 从低周期K线数据中提取高周期K线数据：
	 *          - 支持分钟线、5分钟线、日线等多种周期
	 *          - 可指定周期倍数（如3分钟、15分钟等）
	 *          - 自动处理交易时段的边界
	 *          - 可选择是否包含当前未闭合的K线
	 * 
	 * \note 该方法会创建新的K线数据对象，调用者需要手动释放
	 * \see extractMin1Data(), extractMin5Data(), extractDayData()
	 */
	virtual WTSKlineData*	extractKlineData(WTSKlineSlice* baseKline, WTSKlinePeriod period, uint32_t times, WTSSessionInfo* sInfo, bool bIncludeOpen = true);

	/*!
	 * \brief 从tick数据序列中提取指定秒数的K线数据
	 * 
	 * \param ayTicks tick数据切片
	 * \param seconds 目标秒数（K线周期）
	 * \param sInfo 交易时段模板
	 * \param bUnixTime tick时间戳是否为Unix时间，默认为false
	 * \return 返回构建的K线数据，调用者负责释放内存
	 * 
	 * \details 从tick数据序列构建指定秒数周期的K线数据：
	 *          - 支持任意秒数周期（如30秒、60秒等）
	 *          - 自动计算OHLC数据
	 *          - 累计成交量和成交额
	 *          - 处理不同的时间戳格式
	 * 
	 * \note 该方法主要用于秒级K线的构建
	 * \warning 大量tick数据处理时需要注意内存使用
	 */
	virtual WTSKlineData*	extractKlineData(WTSTickSlice* ayTicks, uint32_t seconds, WTSSessionInfo* sInfo, bool bUnixTime = false);

	/*!
	 * \brief 合并K线数据
	 * 
	 * \param klineData 目标K线数据容器
	 * \param newKline 待合并的K线数据
	 * \return 合并是否成功
	 * 
	 * \details 将两个K线数据集合并为一个：
	 *          - 按时间顺序合并数据
	 *          - 去除重复的时间点
	 *          - 保证数据的连续性
	 *          - 更新内部索引和缓存
	 * 
	 * \note 合并后的数据按时间升序排列
	 * \warning 两个数据集必须具有相同的合约和周期
	 */
	virtual bool			mergeKlineData(WTSKlineData* klineData, WTSKlineData* newKline);

protected:
	/*!
	 * \brief 更新1分钟K线数据（基于tick）
	 * \param sInfo 交易时段信息
	 * \param klineData K线数据容器
	 * \param tick tick数据
	 * \return 更新后的K线结构
	 */
	WTSBarStruct* updateMin1Data(WTSSessionInfo* sInfo, WTSKlineData* klineData, WTSTickData* tick);
	
	/*!
	 * \brief 更新5分钟K线数据（基于tick）
	 * \param sInfo 交易时段信息
	 * \param klineData K线数据容器
	 * \param tick tick数据
	 * \return 更新后的K线结构
	 */
	WTSBarStruct* updateMin5Data(WTSSessionInfo* sInfo, WTSKlineData* klineData, WTSTickData* tick);
	
	/*!
	 * \brief 更新日线数据（基于tick）
	 * \param sInfo 交易时段信息
	 * \param klineData K线数据容器
	 * \param tick tick数据
	 * \return 更新后的K线结构
	 */
	WTSBarStruct* updateDayData(WTSSessionInfo* sInfo, WTSKlineData* klineData, WTSTickData* tick);
	
	/*!
	 * \brief 更新秒线数据（基于tick）
	 * \param sInfo 交易时段信息
	 * \param klineData K线数据容器
	 * \param tick tick数据
	 * \return 更新后的K线结构
	 */
	WTSBarStruct* updateSecData(WTSSessionInfo* sInfo, WTSKlineData* klineData, WTSTickData* tick);

	/*!
	 * \brief 更新1分钟K线数据（基于基础K线）
	 * \param sInfo 交易时段信息
	 * \param klineData K线数据容器
	 * \param newBasicBar 新的基础K线
	 * \return 更新后的K线结构
	 */
	WTSBarStruct* updateMin1Data(WTSSessionInfo* sInfo, WTSKlineData* klineData, WTSBarStruct* newBasicBar);
	
	/*!
	 * \brief 更新5分钟K线数据（基于基础K线）
	 * \param sInfo 交易时段信息
	 * \param klineData K线数据容器
	 * \param newBasicBar 新的基础K线
	 * \return 更新后的K线结构
	 */
	WTSBarStruct* updateMin5Data(WTSSessionInfo* sInfo, WTSKlineData* klineData, WTSBarStruct* newBasicBar);

	/*!
	 * \brief 提取1分钟K线数据
	 * \param baseKline 基础K线数据
	 * \param times 周期倍数
	 * \param sInfo 交易时段信息
	 * \param bIncludeOpen 是否包含未闭合K线
	 * \return 提取的K线数据
	 */
	WTSKlineData* extractMin1Data(WTSKlineSlice* baseKline, uint32_t times, WTSSessionInfo* sInfo, bool bIncludeOpen = true);
	
	/*!
	 * \brief 提取5分钟K线数据
	 * \param baseKline 基础K线数据
	 * \param times 周期倍数
	 * \param sInfo 交易时段信息
	 * \param bIncludeOpen 是否包含未闭合K线
	 * \return 提取的K线数据
	 */
	WTSKlineData* extractMin5Data(WTSKlineSlice* baseKline, uint32_t times, WTSSessionInfo* sInfo, bool bIncludeOpen = true);
	
	/*!
	 * \brief 提取日线数据
	 * \param baseKline 基础K线数据
	 * \param times 周期倍数
	 * \param bIncludeOpen 是否包含未闭合K线
	 * \return 提取的K线数据
	 */
	WTSKlineData* extractDayData(WTSKlineSlice* baseKline, uint32_t times, bool bIncludeOpen = true);

protected:
	/*!
	 * \brief 获取前一个分钟时间点
	 * 
	 * \param curMinute 当前分钟时间
	 * \param period 时间间隔，默认为1分钟
	 * \return 前一个分钟时间点
	 * 
	 * \details 计算指定时间间隔前的分钟时间点，用于K线数据的时间对齐。
	 *          该方法考虑了交易时段的边界处理。
	 */
	static uint32_t getPrevMinute(uint32_t curMinute, int period = 1);
};

